const jwt = require('jsonwebtoken');
const axios = require('axios');
const NodeCache = require('node-cache');
const { exec } = require('child_process');
const cache = new NodeCache();
const fs = require('fs');
const path = require('path');
const appConfig = require('./appConfig');
require("./util/logger");
const zlib = require('zlib');
const parseSalesReport = require('./parseSalesReport');

// 读取配置文件
const configPath = path.join(__dirname, '../public/config.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));

// 读取配置文件中的参数
const { issuerId, keyId2, p8File } = config;
const privateKey = fs.readFileSync(path.join(__dirname, '../public', p8File), 'utf8');

class AppleStoreService {
    constructor(issuerId, keyId2, privateKey) {
        this.issuerId = issuerId;
        this.keyId2 = keyId2;
        this.privateKey = privateKey;
    }

    getToken() {
        let appStoreToken = cache.get('appStoreToken');
        if (!appStoreToken) {
            appStoreToken = this.createToken();
            cache.set('appStoreToken', appStoreToken, 20 * 60); // 20分钟有效期
        }
        return appStoreToken;
    }

    createToken() {
        const now = Math.floor(Date.now() / 1000);
        const payload = {
            iss: this.issuerId,
            iat: now,
            exp: now + 20 * 60, // 20分钟后过期
            aud: 'appstoreconnect-v1'
        };

        const token = jwt.sign(payload, fs.readFileSync(this.privateKey), {
            algorithm: 'ES256',
            header: {
                alg: 'ES256',
                kid: this.keyId2,
                typ: 'JWT'
            }
        });

        console.log('Generated JWT:', token); // 添加日志
        return token;
    }

    /**
     * 通过 curl 命令行方式下载销售报表
     * @param date
     * @param vendorNumber
     * @returns {Promise<unknown>}
     */
    async fetchSalesReportWithCurl(date, vendorNumber, maxRetries = 50) {
        const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

        for (let attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                const token = this.getToken();
                const url = `https://api.appstoreconnect.apple.com/v1/salesReports?filter[reportSubType]=SUMMARY&filter[reportType]=SALES&filter[vendorNumber]=${vendorNumber}&filter[frequency]=DAILY&filter[reportDate]=${date}`;

                const timestamp = Date.now();
                const gzipFilePath = path.join(__dirname, '../public/download', `sales-${date}-daily-${timestamp}-attempt${attempt}.gzip`);
                const txtFilePath = path.join(__dirname, '../public/download', `sales-${date}-daily-${timestamp}-attempt${attempt}.txt`);

                const curlCommand = `curl --location -g --request GET "${url}" \
                                --header "Authorization: Bearer ${token}" \
                                --header "User-Agent: Apifox/1.0.0 (https://apifox.com)" \
                                -o ${gzipFilePath}`;

                const data = await new Promise((resolve, reject) => {
                    exec(curlCommand, async (error, stdout, stderr) => {
                        if (error) {
                            console.error('Error executing curl command:', error);
                            return reject(error);
                        }

                        if (!fs.existsSync(gzipFilePath)) {
                            return reject(new Error('Downloaded gzip file does not exist'));
                        }

                        const fileContents = fs.createReadStream(gzipFilePath);
                        const writeStream = fs.createWriteStream(txtFilePath);
                        const unzip = zlib.createGunzip();

                        unzip.on('error', (streamError) => {
                            if (streamError.code === 'Z_DATA_ERROR') {
                                console.error(date, 'Z_DATA_ERROR: Invalid gzip data');
                                fs.unlinkSync(gzipFilePath);
                                fs.unlinkSync(txtFilePath);
                                reject('Invalid gzip data');
                            } else {
                                console.error('Error during decompression:', streamError);
                                reject(streamError);
                            }
                        });

                        fileContents.pipe(unzip).pipe(writeStream).on('finish', async () => {
                            try {
                                const stats = fs.statSync(txtFilePath);
                                if (stats.size === 0) {
                                    console.error('Decompressed txt file is empty');
                                    fs.unlinkSync(gzipFilePath);
                                    fs.unlinkSync(txtFilePath);
                                    return reject('Decompressed txt file is empty');
                                }

                                const parsedData = await parseSalesReport(txtFilePath);
                                fs.unlinkSync(gzipFilePath);
                                fs.unlinkSync(txtFilePath);
                                resolve(parsedData);
                            } catch (parseError) {
                                console.error('Error parsing sales report:', parseError);
                                reject(parseError);
                            }
                        }).on('error', (streamError) => {
                            console.error('Error during write stream:', streamError);
                            reject(streamError);
                        });
                    });
                });

                // 如果成功执行到这里，返回解析后的数据
                return data;

            } catch (error) {
                console.error(`Attempt ${attempt} failed: ${error}`);
                if (attempt === maxRetries) {
                    throw new Error(`Failed to fetch sales report after ${maxRetries} attempts`);
                }
                // 等待30秒后重试
                await delay(30000);
            }
        }
    }

    async parseAllDownloadedFiles() {
        const downloadDir = path.join(__dirname, '../public/download2');
        try {
            const files = await fs.readdir(downloadDir);
            const gzFiles = files.filter(file => path.extname(file) === '.gz');

            const results = [];

            for (const file of gzFiles) {
                try {
                    const result = await this.parseDownloadedFile(file);
                    results.push({ file, data: result });
                } catch (error) {
                    console.error(`解析文件 ${file} 时出错:`, error);
                    results.push({ file, error: error.message });
                }
            }

            return results;
        } catch (error) {
            console.error('读取目录时出错:', error);
            throw error;
        }
    }

    async parseDownloadedFile(fileName) {
        const gzipFilePath = path.join(__dirname, '../public/download2', fileName);
        const txtFilePath = path.join(__dirname, '../public/download2', fileName.replace('.gz', '.txt'));

        try {
            const compressedData = await fs.readFile(gzipFilePath);
            const decompressedData = await gunzip(compressedData);
            await fs.writeFile(txtFilePath, decompressedData);

            const data = await parseSalesReport(txtFilePath);
            await fs.unlink(txtFilePath);
            return data;
        } catch (error) {
            console.error(`处理文件 ${fileName} 时出错:`, error);
            throw error;
        }
    }
}

new AppleStoreService(issuerId, keyId2, privateKey);

module.exports = AppleStoreService;